import json

from django.db import transaction
from django.shortcuts import render

# Create your views here.
from django_celery_beat.models import PeriodicTask
from rest_framework import status, serializers
from rest_framework.decorators import action
from rest_framework.exceptions import ValidationError
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response

from apitest.models import EnvInfo, ProjectInfo, ModuleInfo, TestApiInfo, TestApiResult, TestCase
from apitest.serializers import EnvInfoModelSerializer, ProjectInfoModelSerializer, ModuleInfoSerializer, \
    TestApiInfoSerializer, TestApiResultSerializer, TestCaseSerializer
from dvadmin.utils.RequestUtil import RequestUtil
from dvadmin.utils.json_response import DetailResponse, ErrorResponse, SuccessResponse
from dvadmin.utils.serializers import CustomModelSerializer
from dvadmin.utils.viewset import CustomModelViewSet


class EnvInfoModelViewSet(CustomModelViewSet):
    """
    list:查询
    create:新增
    update:修改
    retrieve:单例
    destroy:删除
    """
    queryset = EnvInfo.objects.all()
    serializer_class = EnvInfoModelSerializer

    @action(methods=["PUT"], detail=True, permission_classes=[IsAuthenticated])
    @transaction.atomic
    def setDefault(self, request, pk):
        toSet = request.data.get('default', False)
        EnvInfo.objects.filter(id=pk).update(default=toSet)
        if toSet == True:
            EnvInfo.objects.filter(default=True).exclude(id=pk).update(default=False)
            # EnvInfo.objects.filter(default=True,id__ne=pk).update(default=False)
        return DetailResponse(msg="设置成功")


class ProjectInfoViewSet(CustomModelViewSet):
    """
    list:查询
    create:新增
    update:修改
    retrieve:单例
    destroy:删除
    """
    queryset = ProjectInfo.objects.all()
    serializer_class = ProjectInfoModelSerializer


class ModuleInfoViewSet(CustomModelViewSet):
    """
    list:查询
    create:新增
    update:修改
    retrieve:单例
    destroy:删除
    """
    queryset = ModuleInfo.objects.all()
    serializer_class = ModuleInfoSerializer


class TestApiInfoExportSerializer(CustomModelSerializer):
    method_name = serializers.CharField(source='get_method_display', default="")
    project_name = serializers.CharField(source="project_belong.project_name", default="")

    class Meta:
        model = TestApiInfo
        fields = "__all__"


class TestApiInfoImportSerializer(CustomModelSerializer):

    def validate(self, attr):
        project_belong = attr.get('project_belong')
        module_belong = attr.get('module_belong')
        print(project_belong)
        print(module_belong)
        if module_belong.project_belong.id != project_belong.id:
            raise ValidationError({'模块信息错误': '所属模块不在工程里面'})
        return attr

    def save(self, **kwargs):
        name= self.initial_data['name']
        dbapi  = TestApiInfo.objects.filter(name=name).first()
        #修改
        if dbapi:
            dbapi.url = self.get_initial().get("url")
            dbapi.method = self.get_initial().get("method")
            dbapi.headers = self.get_initial().get("headers")
            dbapi.verification = self.get_initial().get("verification")
            dbapi.extract = self.get_initial().get("extract")
            dbapi.params = self.get_initial().get("params")
            dbapi.jsonbody = self.get_initial().get("jsonbody")
            project_id = self.get_initial().get("project_belong")
            if project_id is not None:
                dbapi.project_belong = ProjectInfo.objects.get(pk=project_id)
            module_id = self.get_initial().get("module_belong")
            if module_id is not None:
                dbapi.module_belong = ModuleInfo.objects.get(pk=module_id)
            dbapi.save() #id存在修改 update
        else:
           dbapi = super().save(**kwargs)
        return dbapi

    class Meta:
        model = TestApiInfo
        fields = "__all__"

class TestApiInfoViewSet(CustomModelViewSet):
    """
    list:查询
    create:新增
    update:修改
    retrieve:单例
    destroy:删除
    """
    queryset = TestApiInfo.objects.all()
    serializer_class = TestApiInfoSerializer
    search_fields = ['name']
    # 导出
    export_field_label = {
        "name": "测试用例",
        'method_name': '接口类型',
        "url": "请求地址",
        'create_datetime': '创建时间',
        'headers':'头部信息',
        'project_name':'所属项目'
    }
    export_serializer_class = TestApiInfoExportSerializer

    #导入时候模版
    import_serializer_class = TestApiInfoImportSerializer #导入序列号器
    import_field_dict = {
        "name": "测试用例",
        "url": "请求地址",
        "method": {
            "title": "协议类型",
            "choices": {
                "data": {"GET": 0, "POST": 1, "PUT": 2, 'DELETED': 3},
            }
        },
        "headers": "头部信息(json)",
        "params": "params类型字段(kv)",
        "jsonbody": "json类型字段(json)",
        "verification": "检查点",
        'extract': '关联字段',
        "project_belong": {"title": "工程信息",
                           "choices": {"queryset": ProjectInfo.objects.all(), "values_name": "project_name"}},
        "module_belong": {"title": "模块信息",
                          "choices": {"queryset": ModuleInfo.objects.all(), "values_name": "module_name"}},
    }

    @action(methods=['put'], detail=True)
    @transaction.atomic
    def apiTest(self, request, pk):
        print(pk)
        apiinfo = TestApiInfo.objects.get(id=pk)
        if apiinfo:
            api = RequestUtil()
            env = request.data.get('env')
            if env is not None:
                paramsbody = env.get('paramsbody')
                if paramsbody is not None and paramsbody != '':
                    api.var_pool_data = json.loads(paramsbody)
            url = apiinfo.url
            headers = apiinfo.headers
            verification = apiinfo.verification
            extract = apiinfo.extract

            if apiinfo.params_type == 1:
                # 数据格式 data  id=1&name=test
                params_dic = {}
                if apiinfo.params is not None and apiinfo.params != '':
                    for item in apiinfo.params.split("&"):
                        if len(item.split("=")) == 2:
                            k = item.split("=")[0]
                            v = item.split("=")[1]
                            params_dic[k] = v
                api.send_request(apiinfo.get_method_display(), url,
                                 verification=verification, case_desc=apiinfo.description,
                                 headers=headers, data=params_dic)
            elif apiinfo.params_type == 2 and apiinfo.jsonbody != '':
                api.send_request(apiinfo.get_method_display(), url,
                                 verification=verification, case_desc=apiinfo.description,
                                 headers=headers, json=apiinfo.jsonbody)
            else:
                api.send_request(apiinfo.get_method_display(), url,
                                 verification=verification, case_desc=apiinfo.description,
                                 headers=headers)

            print("测试结果")
            print(api.get_result())
            # 返回结果有异常

            if api.get_result().get('code') == 0:
                return ErrorResponse(msg=api.get_result().get('response'))
            # 写数据库 insert  orm
            testApiResult = TestApiResult()
            testApiResult.api_belong = apiinfo
            testApiResult.project_belong = apiinfo.project_belong
            testApiResult.module_belong = apiinfo.module_belong
            testApiResult.took_time = api.get_result().get("took_time")
            testApiResult.result = api.get_result().get("response")[:200]
            testApiResult.verification = api.get_result().get("check_result")
            testApiResult.env_belong = EnvInfo.objects.get(id=env.get('id'))
            testApiResult.save()
        return DetailResponse(msg="测试成功")


class TestApiResultViewSet(CustomModelViewSet):
    """
    list:查询
    create:新增
    update:修改
    retrieve:单例
    destroy:删除
    """
    queryset = TestApiResult.objects.all()
    serializer_class = TestApiResultSerializer

    @action(methods=['get'], detail=False)
    def count(self, request):
        env = request.query_params.get('env')
        if env:
           env_result= self.get_queryset().filter(env_belong=env).values()
        else:
           env_result = self.get_queryset().values()

        #所有接口
        allApis = len(TestApiInfo.objects.all())
        #当前测试过的接口，从测试结果表中过滤
        testApis = len(env_result.values('api_belong').distinct())
        result_dic ={}
        result_dic['allApis']=allApis
        result_dic['testApis'] =testApis
        result_dic['finshed'] =round(testApis*100/allApis)
        result_dic['total'] = len(env_result)
        pie=[]
        sucess_list=list(filter(lambda elem: elem['verification']=='检查成功',env_result))
        fail_list = list(filter(lambda elem: elem['verification'] == '检查失败', env_result))
        skip_list = list(filter(lambda elem: elem['verification'] == '没有设置检查点', env_result))
        pie.append({'value':len(sucess_list), 'name':'检查成功'})
        pie.append({'value': len(fail_list), 'name': '检查失败'})
        pie.append({'value': len(skip_list), 'name': '跳过检查'})
        result_dic['apicount'] =pie
        return DetailResponse(data=result_dic,msg='返回成功')



class TestCaseViewSet(CustomModelViewSet):
    """
    list:查询
    create:新增
    update:修改
    retrieve:单例
    destroy:删除
    """
    queryset = TestCase.objects.all()
    serializer_class = TestCaseSerializer

    @action(methods=['put'], detail=True)
    @transaction.atomic
    def caseTest(self, request, pk):
        print(pk)
        caseTest = TestCase.objects.get(id=pk)
        if caseTest:
            api = RequestUtil()
            env = request.data.get('env')
            if env is not None:
                paramsbody = env.get('paramsbody')
                if paramsbody is not None and paramsbody != '':
                    api.var_pool_data = json.loads(paramsbody)
            apis = caseTest.apis.all()
            for apiinfo in apis:
                url = apiinfo.url
                headers = apiinfo.headers
                verification = apiinfo.verification
                extract = apiinfo.extract

                if apiinfo.params_type == 1:
                    # 数据格式 data  id=1&name=test
                    params_dic = {}
                    if apiinfo.params is not None and apiinfo.params != '':
                        for item in apiinfo.params.split("&"):
                            if len(item.split("=")) == 2:
                                k = item.split("=")[0]
                                v = item.split("=")[1]
                                params_dic[k] = v
                    api.send_request(apiinfo.get_method_display(), url,
                                     verification=verification, case_desc=apiinfo.description,
                                     headers=headers, data=params_dic, extract=extract)
                elif apiinfo.params_type == 2 and apiinfo.jsonbody != '':
                    api.send_request(apiinfo.get_method_display(), url,
                                     verification=verification, case_desc=apiinfo.description,
                                     headers=headers, json=apiinfo.jsonbody, extract=extract)
                else:
                    api.send_request(apiinfo.get_method_display(), url,
                                     verification=verification, case_desc=apiinfo.description,
                                     headers=headers, extract=extract)

                print("测试结果")
                print(api.get_result())
                testApiResult = TestApiResult()
                testApiResult.api_belong = apiinfo
                testApiResult.project_belong = apiinfo.project_belong
                testApiResult.module_belong = apiinfo.module_belong
                testApiResult.took_time = api.get_result().get("took_time")
                testApiResult.result = api.get_result().get("response")[:200]
                testApiResult.verification = api.get_result().get("check_result")
                testApiResult.env_belong = EnvInfo.objects.get(id=env.get('id'))
                testApiResult.case_belong = caseTest
                testApiResult.save()
        return DetailResponse(msg="测试成功")

    @transaction.atomic
    def destroy(self, request, *args, **kwargs):
        instance = self.get_object()
        #关联的定时任务
        taskid = instance.task_id
        if taskid is not None and taskid!='':
            try:
                task = PeriodicTask.objects.get(id=taskid)
                task.delete()
            except Exception as e:
                print(e)
                pass
        instance.delete()
        return SuccessResponse(msg='删除成功')

    @action(methods=['delete'], detail=False)
    def multiple_delete(self, request, *args, **kwargs):
        request_data = request.data
        keys = request_data.get('keys', None)
        taskid_list = list(TestCase.objects.filter(id__in=keys).values_list('task_id',flat=True))
        if keys:
            PeriodicTask.objects.filter(id__in=taskid_list).delete()
            self.get_queryset().filter(id__in=keys).delete()
            return SuccessResponse(data=[], msg="删除成功")
        else:
            return ErrorResponse(msg="未获取到keys字段")
